package com.na.tools.ping;

import java.io.InputStream;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;

import com.na.tools.CommonTools;
import com.na.tools.ping.NetworkChecker.BatchNetworkChecker;
import com.na.tools.ping.NetworkChecker.Host;

public class Main {

	static class Config {
		final BatchNetworkChecker networkChecker;
		final HostFetcher hostFetcher;
		final String hostFile;
		Config(String checker, String fetcher, String file) {
			networkChecker = Factory.create(checker);
			hostFetcher = Factory.create(fetcher);
			hostFile = file;
		}
	}
	
	static final String[] NETWORK_CHECKER = {
		"com.na.tools.ping.impl.SocketNetworkChecker", // 0
		"com.na.tools.ping.impl.CommondNetworkChecker" // 1
	};
	static final String[] HOST_FETCHER = {
		"com.na.tools.ping.Main$CaHostFetcher", // 0
		"com.na.tools.ping.Main$ChinazHostFetcher" // 1
	};
	static final String[] HOST_FILES = {
		"ca.com.txt", // 0
		"ping.chinaz.com.txt" // 1
	};
	
	static final Config SOCKET_CA = new Config(NETWORK_CHECKER[0], HOST_FETCHER[0], HOST_FILES[0]);
	static final Config SOCKET_CHINAZ = new Config(NETWORK_CHECKER[0], HOST_FETCHER[1], HOST_FILES[1]);
	static final Config CMD_CA = new Config(NETWORK_CHECKER[1], HOST_FETCHER[0], HOST_FILES[0]);
	static final Config CMD_CHINAZ = new Config(NETWORK_CHECKER[1], HOST_FETCHER[1], HOST_FILES[1]);
	
	public static void main(String[] args) {
		Config config = SOCKET_CA;
//		Config config = SOCKET_CHINAZ;
//		Config config = CMD_CA;
//		Config config = CMD_CHINAZ;
		
		String[] hosts = config.hostFetcher.fetch(Main.class.getResourceAsStream(config.hostFile));
		Host[] h = config.networkChecker.batchConnect(hosts);
		Arrays.sort(h);
		CommonTools.printArray(h, "\n");
	}
	
	static class Factory {
		static <T> T create(Class<T> cls) {
			try {
				return cls.newInstance();
			} catch (Exception e) {}
			return null;
		}
		static <T> T create(String className) {
			try {
				Class cls = Class.forName(className);
				Object obj = cls.newInstance();
				return (T) obj;
			} catch (Exception e) {}
			return null;
		}
	}
	
	static interface HostFetcher {
		String[] fetch(InputStream in);
	}
	
	static class CaHostFetcher implements HostFetcher {
		@Override
		public String[] fetch(InputStream in) {
			byte[] b = CommonTools.readFile(in);
			String[] strs = CommonTools.split(new String(b), "\t", System.lineSeparator());
			Set<String> hosts = new LinkedHashSet<String>();
			// fetch host in position 5(step 6)
			for (int i = 5; i < strs.length; i += 6) {
				hosts.add(strs[i]);
			}
			return hosts.toArray(new String[hosts.size()]);
		}
	}
	
	static class ChinazHostFetcher implements HostFetcher {
		@Override
		public String[] fetch(InputStream in) {
			byte[] b = CommonTools.readFile(in);
			String[] strs = CommonTools.split(new String(b), System.lineSeparator());
			Set<String> hosts = new LinkedHashSet<String>();
			// fetch host in position 1(step 6)
			for (int i = 1; i < strs.length; i += 6) {
				hosts.add(strs[i]);
			}
			return hosts.toArray(new String[hosts.size()]);
		}
	}
}
